import logging
from pathlib import Path
from logging.handlers import RotatingFileHandler
from typing import Optional, Union


class Logger:
    """增强型日志工具类，相同name只会创建一个实例，确保日志写入同一文件"""

    # 类变量存储已创建的实例，实现单例模式
    _instances = {}

    def __new__(cls, name: str, *args, **kwargs):
        """控制实例创建，相同name返回同一个实例"""
        if name not in cls._instances:
            cls._instances[name] = super().__new__(cls)
        return cls._instances[name]

    def __init__(
            self,
            name: str,
            log_file: Optional[str] = None,
            level: Union[str, int] = logging.INFO,
            max_bytes: int = 10 * 1024 * 1024,  # 10MB
            backup_count: int = 5,
            fmt: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    ):
        # 防止重复初始化
        if hasattr(self, '_initialized') and self._initialized:
            return

        self.name = name
        self.logger = logging.getLogger(name)

        # 处理日志级别
        self.level = self._parse_level(level)
        self.logger.setLevel(self.level)

        # 若未指定日志文件名，直接使用名称.log
        if not log_file:
            log_file = f"{name}.log"

        # 避免重复添加处理器
        if not self.logger.handlers:
            self._setup_handlers(log_file, max_bytes, backup_count, fmt)
            self.logger.info(f"日志初始化完成，日志文件存储于: {self.log_path.resolve()}")

        self._initialized = True

    def _parse_level(self, level: Union[str, int]) -> int:
        if isinstance(level, str):
            level = level.upper()
            level_map = {
                "DEBUG": logging.DEBUG,
                "INFO": logging.INFO,
                "WARNING": logging.WARNING,
                "ERROR": logging.ERROR,
                "CRITICAL": logging.CRITICAL
            }
            return level_map.get(level, logging.INFO)
        return level

    def _setup_handlers(
            self,
            log_file: str,
            max_bytes: int,
            backup_count: int,
            fmt: str
    ) -> None:
        formatter = logging.Formatter(fmt)

        # 控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setFormatter(formatter)
        console_handler.setLevel(self.level)

        # 日志目录（基于脚本路径的绝对路径）
        current_script = Path(__file__).resolve()
        project_root = current_script.parent.parent  # 根据实际结构调整
        self.log_dir = project_root / "artifacts" / "logs"
        self.log_dir.mkdir(parents=True, exist_ok=True)
        self.log_path = self.log_dir / log_file

        # 文件轮转处理器
        file_handler = RotatingFileHandler(
            self.log_path,
            maxBytes=max_bytes,
            backupCount=backup_count,
            encoding="utf-8"
        )
        file_handler.setFormatter(formatter)
        file_handler.setLevel(self.level)

        self.logger.addHandler(console_handler)
        self.logger.addHandler(file_handler)

    def get_logger(self) -> logging.Logger:
        return self.logger

    @classmethod
    def quick_init(cls, name: str, **kwargs) -> logging.Logger:
        """快速初始化，默认level为INFO，log_file为name.log"""
        kwargs.setdefault('level', "INFO")
        kwargs.setdefault('log_file', f"{name}.log")
        return cls(name, **kwargs).get_logger()


# 使用示例
if __name__ == "__main__":
    # 第一次初始化
    logger1 = Logger.quick_init(name="price_predictor")
    logger1.info("这是logger1的日志")

    # 第二次初始化相同名称
    logger2 = Logger.quick_init(name="price_predictor")
    logger2.info("这是logger2的日志，会写入同一个文件")

    # 验证是否为同一个实例
    print(f"logger1和logger2是否为同一对象: {logger1 is logger2}")
